﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonLib;
using DBHelperLib;
using System.Data.Common;
using System.Data;

namespace CommonDAL
{
    public abstract class DataEntityOld2<TBusinessEntity> : IDataEntity
        where TBusinessEntity : IBusinessEntity
    {
        public abstract event EventHandler Dirty;
        public abstract event EventHandler<ConstraintIntegrityEventArgs> ConstraintIntegrity;

        public abstract long? Identity { get; protected set; }

        public abstract bool IsNew { get; }

        public int Update()
        {
            if (IsNew)
                throw new ApplicationException("The data entity is new and can't be updated!");

            return UpdateEntity();
        }

        public long Create()
        {
            if (!IsNew)
                throw new ApplicationException("The data entity is not new and can't be inserted!");

            return InsertEntity();
        }

        public int Delete()
        {
            if (IsNew)
                throw new ApplicationException("The data entity is new and can't be deleted!");

            return DeleteEntity();
        }

        protected abstract TBusinessEntity BusinessEntity { get; }

        protected abstract int UpdateEntity();
        protected abstract long InsertEntity();
        protected abstract int DeleteEntity();

        #region IDataEntity Members


        void IDataEntity.Create()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IDataEntity Members

        event EventHandler<DirtyEventArgs> IDataEntity.Dirty
        {
            add { throw new NotImplementedException(); }
            remove { throw new NotImplementedException(); }
        }

        public DataEntityState EntityState
        {
            get { throw new NotImplementedException(); }
        }

        #endregion

        #region IDataEntity Members


        public bool IsDirty
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }

    public abstract class DataEntity<TIdentity, TUniqueKey, TBusinessEntity> :
        IDataEntity<TIdentity, TUniqueKey, TBusinessEntity>
        where TIdentity : struct
        where TUniqueKey : struct
        where TBusinessEntity : class, IBusinessEntity<TUniqueKey>
    {
        public event EventHandler<DirtyEventArgs> Dirty;
        public event EventHandler<ConstraintIntegrityEventArgs> ConstraintIntegrity;

        private TIdentity? _identity;
        private TBusinessEntity _businessEntity;
        private long _version;

        public DataEntity(
            TIdentity identity,
            TBusinessEntity businessEntity,
            long version) :

            this(new TIdentity?(identity), businessEntity, version)
        {
        }

        public DataEntity(
            TBusinessEntity businessEntity) :

            this(null, businessEntity, 1)
        {
        }

        private DataEntity(
            TIdentity? identity,
            TBusinessEntity businessEntity,
            long version)
        {
            Identity = identity;
            BusinessEntity = businessEntity;
            Version = version;
        }

        public TIdentity? Identity
        {
            get { return _identity; }
            set
            {
                if (Identity.HasValue)
                    throw new ApplicationException("The data entity identity can't be changed");

                _identity = value;
            }
        }

        public TUniqueKey UniqueKey
        {
            get { return BusinessEntity.UniqueKey; }
        }

        public TBusinessEntity BusinessEntity
        {
            get { return _businessEntity; }
            protected set { _businessEntity = value; }
        }

        public long Version
        {
            get { return _version; }
            set { _version = value; }
        }

        public bool IsNew
        {
            get { return !Identity.HasValue; }
        }

        public bool IsDirty
        {
            get { return _isDirty; }
            protected set { _isDirty = value; }
        }

        public DataEntityState EntityState
        {
            get
            {
                if (IsNew)
                    return DataEntityState.New;

                if (_isDirty)
                    return DataEntityState.Dirty;

                return DataEntityState.Clean;
            }
        }

        public int Update()
        {
            if (IsNew)
                throw new ApplicationException("The data entity is new and can't be updated!");

            if (!_isDirty)
                return 1;

            int rowsAffected = UpdateEntity();

            _isDirty = false;

            return rowsAffected;
        }

        public TIdentity Insert()
        {
            if (!IsNew)
                throw new ApplicationException("The data entity is not new and can't be inserted!");

            return InsertEntity();
        }

        public int Delete()
        {
            if (IsNew)
                throw new ApplicationException("The data entity is new and can't be deleted!");

            return DeleteEntity();
        }

        public void Create()
        {
            Insert();
        }

        private bool _isDirty = false;

        protected virtual void OnDirty()
        {
            if (_isDirty || IsNew)
                return;

            _isDirty = true;

            if (Dirty == null)
                return;

            Dirty(this, new DirtyEventArgs(this));
        }

        protected abstract int UpdateEntity();
        protected abstract TIdentity InsertEntity();
        protected abstract int DeleteEntity();
    }


    public interface IMyBusinessEntity : IBusinessEntity<long>
    {
    }

    public class MyBusinessEntity : IMyBusinessEntity
    {
        #region IBusinessEntity<long> Members

        public long UniqueKey
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }

    public class MyDataEntity : DataEntity<long, long, IMyBusinessEntity>, IMyBusinessEntity
    {
        public MyDataEntity(long identity, IMyBusinessEntity businessEntity, long version) :
            base(identity, businessEntity, version)
        {
        }

        public MyDataEntity(IMyBusinessEntity businessEntity)
            : base(businessEntity)
        {
        }

        protected override int UpdateEntity()
        {
            throw new NotImplementedException();
        }

        protected override long InsertEntity()
        {
            throw new NotImplementedException();
        }

        protected override int DeleteEntity()
        {
            throw new NotImplementedException();
        }
    }

    public class MyLazyEntity : LazyDataEntity<long, long, IMyBusinessEntity, MyDataEntity>, IMyBusinessEntity
    {
        public MyLazyEntity(long identity, MyDataMapper myDm) : base(identity, myDm)
        {

        }
        #region IBusinessEntity<long> Members

        long IBusinessEntity<long>.UniqueKey
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }
}
